package org.joshsacks.fishies.ui.gl;

import static javax.microedition.khronos.opengles.GL10.GL_FLOAT;
import static javax.microedition.khronos.opengles.GL10.GL_UNSIGNED_SHORT;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

public class SquareRenderer {
  private static final float[] SQUARE_COORDINATES = { 
          0, 0, 
          0, 1.0f,
          1.0f, 1.0f, 
          1.0f, 0,
  };   
  private static final float[] textureIndexes;
  private static final float[] flippedTextureIndexes;
  
  static {
    textureIndexes = new float[4 * 2];
    int index = 0;
    for (int i = 0; i < 4; i++) {
      textureIndexes[index++] = SQUARE_COORDINATES[i*2];
      textureIndexes[index++] = 1 - SQUARE_COORDINATES[i*2+1];
    }
    
    flippedTextureIndexes = new float[4 * 2];
    index = 0;
    for (int i = 0; i < 4; i++) {
      flippedTextureIndexes[index++] = 1 - SQUARE_COORDINATES[i*2];
      flippedTextureIndexes[index++] = 1 - SQUARE_COORDINATES[i*2+1];
    }
  }
  
  private final GL10 gl;
  private static final FloatBuffer textureBuffer = 
    ByteBuffer.allocateDirect(1000).order(ByteOrder.nativeOrder()).asFloatBuffer();
  private static final ByteBuffer indexBuffer = 
    ByteBuffer.allocateDirect(1000).order(ByteOrder.nativeOrder());
  private static final ByteBuffer pointBuffer = 
    ByteBuffer.allocateDirect(1000).order(ByteOrder.nativeOrder());
  private int points;
  
  public SquareRenderer(GL10 gl) {
    this.gl = gl;
    points = 0;
    textureBuffer.position(0);
    indexBuffer.position(0);
    pointBuffer.position(0);
  }

  public void addSquare(float x, float y, int size, boolean flipTexure) { 
   textureBuffer.put(flipTexure ? flippedTextureIndexes : textureIndexes);
   for (int point = 0; point < 4; point++) {
     pointBuffer.putFloat((SQUARE_COORDINATES[point * 2] * size + x));
     pointBuffer.putFloat((SQUARE_COORDINATES[point * 2 + 1] * size + y));
     pointBuffer.putFloat(0);
   }  
   indexBuffer.putShort((short) points);
   indexBuffer.putShort((short) (points + 1));
   indexBuffer.putShort((short) (points + 2));

   indexBuffer.putShort((short) (points + 3));
   indexBuffer.putShort((short) points);
   indexBuffer.putShort((short) (points + 2));
   points += 4;
  }

  public void addRectangle(float x, float y, int sizeX, int sizeY, float[] textureCoor) { 
    if (textureCoor != null) {
      textureBuffer.put(textureCoor);
    }
    for (int point = 0; point < 4; point++) {
      pointBuffer.putFloat((SQUARE_COORDINATES[point * 2] * sizeX + x));
      pointBuffer.putFloat((SQUARE_COORDINATES[point * 2 + 1] * sizeY + y));
      pointBuffer.putFloat(0);
    }  
    indexBuffer.putShort((short) points);
    indexBuffer.putShort((short) (points + 1));
    indexBuffer.putShort((short) (points + 2));

    indexBuffer.putShort((short) (points + 3));
    indexBuffer.putShort((short) points);
    indexBuffer.putShort((short) (points + 2));
    points += 4;
   }

  public void draw() {
    pointBuffer.position(0);
    indexBuffer.position(0);
    textureBuffer.position(0);
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, pointBuffer);     
    gl.glTexCoordPointer(2, GL_FLOAT, 0, textureBuffer);
    gl.glDrawElements(GL10.GL_TRIANGLES, points / 4 * 6, GL_UNSIGNED_SHORT, indexBuffer);      
  }
}
